package cntv.player.core;

import cntv.player.core.util.LogUtil;
import cntv.player.core.util.SprefUtils;
import cntv.player.core.util.Utils;
import cntv.player.engine.ThreadPool;

import com.cntv.cbox.player.core.CBoxP2PCore;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;

public class CBoxP2P {
	private static CBoxP2P mCBoxP2P;
	private Context mContext;
	private ThreadPool threadPool;
	private CBoxP2PCore mCBoxP2PCore;
	private P2PInitTask pInitTask;
	private P2PBufferTask bufferTask;

	private String clientId;
	private String port, playId, bufferStr;

	private String r = "0";// 码率,p2p时播放成功值为500，播放不成功为0
	private String cr = "0";// 码率,p2p时播放成功值为500，播放不成功为0

	private static final int NUM_P2PINIT = 50; // p2p初始化接次数修改为50
	private static final int NUM_TIMEOUT = 50; // p2p缓冲超时连接次数修改为50
	private static final int NUM_ERROR = 10; // p2p错误时，连接次数默认10
	private int mTimeoutTryCount;// 超时尝试次数
	private int mErrorTryCount; // 错误尝试次数
	private int mP2pInitTryCount;//p2p初始化尝试次数

	private OnP2PInitListener mOnP2PInitListener;
	private OnP2PBufferListener mOnP2PBufferListener;
	private Handler p2pHandler = new Handler() {
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case CBoxStaticParam.P2P_INIT_UPDATE:
				if (mOnP2PInitListener != null) {
					mOnP2PInitListener.p2pInitUpdate((String) msg.obj);
				}
				p2pInit();
				break;
			case CBoxStaticParam.P2P_INIT:
				mP2pInitTryCount++;
				if(mP2pInitTryCount >= NUM_P2PINIT){
					LogUtil.i("zl", "CboxP2P Handler P2P_INIT end........................p2pInit failed");
//					SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", false);
					CBoxStaticParam.P2P_INIT_SUCCESS_STATE = false;
					mP2pInitTryCount = 0;
					if (mOnP2PInitListener != null) {
						mOnP2PInitListener.p2pInitFailed();
					}
				}else{
					p2pInit();
				}
				break;
			case CBoxStaticParam.P2P_INIT_SUCCESS:
				LogUtil.i("zl", "CboxP2P Handler P2P_INIT_SUCCESS end....................p2pInit success");
//				SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", true);
				CBoxStaticParam.P2P_INIT_SUCCESS_STATE = true;
				LogUtil.i("zl", "CboxP2P p2pBuffer start.......................p2pBuffer start");
				p2pBuffer();
				mP2pInitTryCount = 0;
				if (mOnP2PInitListener != null) {
					mOnP2PInitListener.p2pInitSuccess();
				}
				break;
			case CBoxStaticParam.P2P_INIT_FAIL:
				LogUtil.i("zl", "CboxP2P Handler P2P_INIT_FAIL end....................p2pInit failed");
//				SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", false);
				CBoxStaticParam.P2P_INIT_SUCCESS_STATE = false;
				mP2pInitTryCount = 0;
				String errorCode = (String) msg.obj;
				LogUtil.i("zl", "P2P_INIT_FAIL  errorCode = " + errorCode);
				if (mOnP2PInitListener != null) {
					mOnP2PInitListener.p2pInitFailed();
				}
				if (mOnP2PBufferListener != null) {
					mOnP2PBufferListener.p2pBufferFailed(601, "p2p初始化失败,请重试");
				}
				break;
			case CBoxStaticParam.P2P_BUFFER:
				int bufferNum = 0;
				try {
					bufferNum = (Integer) msg.obj;
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (bufferNum == 404) {
					mTimeoutTryCount++;
				}
				if (bufferNum == 0) {
					mErrorTryCount++;
				}
				LogUtil.i("zl", "bufferNum = " + bufferNum + ",mTimeoutTryCount = " + mTimeoutTryCount + ",mErrorTryCount = " + mErrorTryCount);
				if (mTimeoutTryCount >= NUM_TIMEOUT || mErrorTryCount >= NUM_ERROR) {// p2p连接超时或者错误
					// p2pEnd(playId, "r=" + r + "&cr=" + cr);
//					SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", false);
					CBoxStaticParam.P2P_INIT_SUCCESS_STATE = false;//如果出现缓冲超时，或者缓冲错误，重置p2p初始化状态，重新初始化p2p插件
					LogUtil.i("zl", "CboxP2P p2pBuffer end...........................p2pBuffer failed");
					if (mOnP2PBufferListener != null) {
						stopBuffering();
						mOnP2PBufferListener.p2pBufferFailed(600, "p2p连接超时,请重试");
					}
				} else {
					p2pBuffer();
				}
				break;
			case CBoxStaticParam.P2P_BUFFER_SUCCESS:
				String p2pUrl = createPlayUrl();
				LogUtil.i("zl", "CboxP2P p2pBuffer end.......................p2pBuffer success");
				if (mOnP2PBufferListener != null) {
					mOnP2PBufferListener.p2pBufferSuccess(p2pUrl);
					stopBuffering();
				}
				break;
			case CBoxStaticParam.P2P_BUFFER_FAIL:
				// p2pFinish(playId);
				Bundle data = msg.getData();
				if(data.getInt("errNum") == 9999){
//					SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", false);
					CBoxStaticParam.P2P_INIT_SUCCESS_STATE = false;//如果出现缓冲未知异常，重置p2p初始化状态，重新初始化p2p插件
				}
				LogUtil.i("zl", "CboxP2P p2pBuffer end................p2pBuffer failed");
				if (mOnP2PBufferListener != null) {
					mOnP2PBufferListener.p2pBufferFailed(data.getInt("errNum"),data.getString("errMsg"));
					stopBuffering();
				}
				break;
			default:
				break;
			}
		};
	};

	private CBoxP2P(Context context) {
//		this.clientId = "cntv.cn." + (int) (Math.random() * 100000000 + 1);
		this.clientId = context.getPackageName();
		threadPool = ThreadPool.getInstance();
		this.mCBoxP2PCore = CBoxP2PCore.getInstance();
		this.mContext = context;
	}

	public static CBoxP2P getInstance(Context context) {
		if (mCBoxP2P == null) {
			mCBoxP2P = new CBoxP2P(context);
//			SprefUtils.getInstance(context).putBoolean("p2pInitSuccess", false);
			CBoxStaticParam.P2P_INIT_SUCCESS_STATE = false;//重置p2p初始化成功状态，必须重新初始化p2p插件
		}
		return mCBoxP2P;
	}

	/**
	 * 子线程中检查版本或者升级启动
	 */
	private void p2pInit() { 
		pInitTask = new P2PInitTask(mContext, p2pHandler);
		threadPool.execute(pInitTask);
	}

	/**
	 * 子线程中p2p播放缓冲开始，传入参数等待频道启动成功
	 */
	public void play(String playId) {
		this.playId = playId;
		
		isNetChanged();
//			if (!SprefUtils.getInstance(mContext).getBoolean("p2pInitSuccess")) {
		if (!CBoxStaticParam.P2P_INIT_SUCCESS_STATE) {
			LogUtil.i("zl", "CboxP2P play(playId) p2pInit start......................p2pInit start");
			p2pInit();
		}else{
			LogUtil.i("zl", "CboxP2P p2pBuffer start....................p2pBuffer start");
			p2pBuffer();
		}
	}
	
	/**
	 * 判断网络是否变化
	 * 网络变化后p2p需要重新缓冲，否则播放失败
	 * @return true为网络变化了，false未变化
	 */
	private boolean isNetChanged(){
		int lastNetType = SprefUtils.getInstance(mContext).getInt("netType",-1);
		int nowNetType = Utils.getNetType(mContext);
		
		boolean isNetChanged = nowNetType != lastNetType;
		LogUtil.i("zl", "CboxP2P isNetChanged = " + isNetChanged);
		SprefUtils.getInstance(mContext).putInt("netType", nowNetType);
		
		//如果p2pInitSuccess 为true，但网络发生了变化，重置p2pInitSuccess状态为false,必须重新初始化p2p插件
		//如果p2pInitSuccess为false，无论网络变化与否，p2pInitSuccess状态仍为false，都必须重新初始化p2p插件
		/*if (SprefUtils.getInstance(mContext).getBoolean("p2pInitSuccess")) {
			SprefUtils.getInstance(mContext).putBoolean("p2pInitSuccess", !isNetChanged);
		}*/
		if(CBoxStaticParam.P2P_INIT_SUCCESS_STATE){
			CBoxStaticParam.P2P_INIT_SUCCESS_STATE = !isNetChanged;
		}
		
		return isNetChanged;
	}
	
	/**
	 * p2p直播开始缓冲
	 */
	private void p2pBuffer(){ 
		bufferStr = createBufferString();// 用到playId
		bufferTask = new P2PBufferTask(bufferStr, p2pHandler);
		threadPool.execute(bufferTask);
	}

	private String createBufferString() {
		String verTag = "&Ver=1&";
		if (Utils.systemVersions() >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
			verTag = "&Ver=0&";
		}
		return "GetBufferState:ClientID=" + clientId + "&ChannelID=" + playId + verTag;
	}

	public void stopBuffering() {
		mTimeoutTryCount = 0;// 将计数归0
		mErrorTryCount = 0;// 将计数归0
		p2pHandler.removeMessages(CBoxStaticParam.P2P_BUFFER);
	}

	public String stopChannel() {
		String arg = "StopChannel:ClientID=" + clientId + "&ChannelID=" + playId;
		return mCBoxP2PCore.InstanceGetP2PState(arg);
	}

	public String createPlayUrl() {
		if (port == null) {
			port = mCBoxP2PCore.InstanceGetP2PState("GetWebPort:void");
		}
		return "http://127.0.0.1:" + port + "/plug_in/M3u8Mod/LiveStream.m3u8?ClientID=" + clientId + "&ChannelID=" + playId;
	}

	private String p2pStats(String arg) {
		String str = "";
		if (!TextUtils.isEmpty(arg)) {
			str = mCBoxP2PCore.InstanceGetP2PState(arg);
		}
		return str;
	}

	/**
	 * 核心版本号
	 **/
	public String p2pCoreVN() {
		return mCBoxP2PCore.InstanceGetCurVN();
	}

	/**
	 * 统计信息-开始缓冲
	 **/
	public void p2pBegin(String id, String info) {
		p2pStats("SetGSInfor:state=" + id + "+beginload&" + info);
	}

	/**
	 * 统计信息-缓冲结束
	 **/
	public void p2pEnd(String id, String info) {
		p2pStats("SetGSInfor:state=" + id + "+endload&" + info);
	}

	/**
	 * 传入其他需要统计的信息。如：页面地址.频道名称.浏览器信息...等(串名=串值&串名=串值&串名=串值)
	 * 
	 * @return
	 **/
	public String p2pSetInfo(String info) {
		return p2pStats("SetGSInfor:" + info);
	}

	/**
	 * 在播放过程中暂停和串值更新(串名=串值&串名=串值&串名=串值)
	 **/
	public void p2pPauseInfo(String id, String info) {
		LogUtil.w("zl", "p2pPauseInfo: id = " + id + ",info = " + info);
		String setInfo = "SetGSInfor:state=" + id + "+pause";
		if (!TextUtils.isEmpty(info)) {
			setInfo += "&&" + info;
		}
		p2pStats(setInfo);
	}

	/**
	 * 在播放过程中重新播放和串值更新(串名=串值&串名=串值&串名=串值)
	 **/
	public void p2pPlayInfo(String id, String info) {
		LogUtil.w("zl", "p2pPlayInfo: id = " + id + ",info = " + info);
		String setInfo = "SetGSInfor:state=" + id + "+play";
		if (!TextUtils.isEmpty(info)) {
			setInfo += "&&" + info;
		}
		p2pStats(setInfo);
	}

	/**
	 * 在播放过程中卡顿和串值更新(串名=串值&串名=串值&串名=串值)
	 **/
	public void p2pLockInfo(String id, String info) {
		LogUtil.w("zl", "p2pLockInfo: id = " + id + ",info = " + info);
		String setInfo = "SetGSInfor:state=" + id + "+bufwait";
		if (!TextUtils.isEmpty(info)) {
			setInfo += "&&" + info;
		}
		p2pStats(setInfo);
	}

	/**
	 * 在播放过程中恢复和串值更新(串名=串值&串名=串值&串名=串值)
	 **/
	public void p2pReaginInfo(String id, String info) {
		LogUtil.w("zl", "p2pReaginInfo: id = " + id + ",info = " + info);
		String setInfo = "SetGSInfor:state=" + id + "+bufend";
		if (!TextUtils.isEmpty(info)) {
			setInfo += "&&" + info;
		}
		p2pStats(setInfo);
	}

	/**
	 * 频道播放结束-统计模块结束统计信息报告
	 **/
	public void p2pFinish(String id) {
		p2pStats("SetGSInfor:state=" + id + "+end");
	}

	public void setOnP2PInitListener(OnP2PInitListener mOnP2PInitListener) {
		this.mOnP2PInitListener = mOnP2PInitListener;
	}

	public void setOnP2PBufferListener(OnP2PBufferListener mOnP2PBufferListener) {
		this.mOnP2PBufferListener = mOnP2PBufferListener;
	}

	public interface OnP2PInitListener {
		public void p2pInitSuccess();

		public void p2pInitUpdate(String msgInfo);

		public void p2pInitFailed();
	}

	public interface OnP2PBufferListener {
		public void p2pBufferSuccess(String p2pUrl);

		public void p2pBufferFailed(int errNum, String errInfo);
	}
}
